package javabasics.thread.lock;

import java.util.concurrent.locks.StampedLock;

/**
 * @Author suxiaoxiao
 * @Date 2019/7/28 13:43
 * @Version 1.0
 */
public class Point {

    private double x, y;
    private final StampedLock s1 = new StampedLock();

    void move(double deltaX, double deltaY) {
        // 获取写锁
        // 涉及对共享资源的修改，使用写锁 - 独占操作
        long stamp = s1.writeLock();
        try {
            x += deltaX;
            y += deltaY;
        } finally {
            // 释放写锁
            s1.unlockWrite(stamp);
        }
    }

    /**
     * 使用乐观锁访问共享资源
     * @return
     */
    double distanceFormOrigin() {
        // 乐观读操作
        long stamp = s1.tryOptimisticRead();
        // 拷贝变量
        double currentX = x, currentY = y;
        // 判断是否有写操作
        // 如果有写操作，为了避免数据不一致，切换为悲观读。
        if (!s1.validate(stamp)) {
            // 升级为悲观读
            stamp = s1.readLock();
            try {
                currentX = x;
                currentY = y;
            } finally {
                s1.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }

    void moveIfAtOrigin(double newX, double newY) {
        long stamp = s1.readLock();
        try {
            while (x == 0.0 && y == 0.0) {
                long ws = s1.tryConvertToWriteLock(stamp);
                if (ws != 0L) {
                    stamp = ws;
                    x = newX;
                    y = newY;
                    break;
                } else {
                    s1.unlockRead(stamp);
                    stamp = s1.writeLock();
                }
            }
        } finally {
            s1.unlockRead(stamp);
        }
    }

}
